package com.ruihu.admin.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.util.List;

@Slf4j
public class RhJsonUtil {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    static {
        OBJECT_MAPPER.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_FORMAT));
        OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        OBJECT_MAPPER.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
        OBJECT_MAPPER.configure(SerializationFeature.INDENT_OUTPUT, Boolean.TRUE);
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        OBJECT_MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
    }

    public static String toJson(Object obj, String datePattern) {
        try {
            OBJECT_MAPPER.setDateFormat(new SimpleDateFormat(datePattern));
            String result = OBJECT_MAPPER.writeValueAsString(obj);
            OBJECT_MAPPER.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_FORMAT));
            return result;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static String toJson(Object obj) {
        try {
            return OBJECT_MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return null;
    }


    public static <T> T parseJson(String json, TypeReference<T> valueTypeRef) {
        try {
            return OBJECT_MAPPER.readValue(json, valueTypeRef);
        } catch (JsonProcessingException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public static <T> T parseJson(String json, Class<T> valueType) {
        try {
            return OBJECT_MAPPER.readValue(json, valueType);
        } catch (JsonProcessingException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public static <T> T parseJsonNode(String json, String path, TypeReference<T> valueTypeRef) {
        try {
            JsonNode node = OBJECT_MAPPER.readTree(json);
            JsonNode jsonNode = node.at(path);
            return OBJECT_MAPPER.convertValue(jsonNode, valueTypeRef);
        } catch (JsonProcessingException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public static JsonNode getJsonNode(String json, String path) {
        try {
            JsonNode jsonNode = OBJECT_MAPPER.readTree(json);
            return jsonNode.at(path);
        } catch (JsonProcessingException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public static <T> T convertValue(JsonNode jsonNode, TypeReference<T> valueTypeRef) {
        return OBJECT_MAPPER.convertValue(jsonNode, valueTypeRef);
    }

    public static <T> T convertValue(JsonNode jsonNode, Class<T> valueType) {
        return OBJECT_MAPPER.convertValue(jsonNode, valueType);
    }

    public static <T> List<T> parseList(String json) {
        try {
            return OBJECT_MAPPER.readValue(json, new TypeReference<List<T>>() {});
        } catch (JsonProcessingException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public static <T> List<T> parseList(String json, String path, TypeReference<List<T>> valueTypeRef) {
        try {
            JsonNode node = OBJECT_MAPPER.readTree(json);
            JsonNode jsonNode = node.at(path);
            return OBJECT_MAPPER.convertValue(jsonNode, valueTypeRef);
        } catch (JsonProcessingException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }
    
    public static ObjectMapper objectMapper() {
        return OBJECT_MAPPER;
    }

}
